package com.ctrip.xpipe.migration;

import com.ctrip.xpipe.api.migration.OuterClientException;
import com.ctrip.xpipe.endpoint.HostPort;
import com.ctrip.xpipe.utils.DateTimeUtils;
import com.google.common.collect.Lists;

import java.net.InetSocketAddress;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author shyin
 *
 *         Dec 22, 2016
 */
public class DefaultOuterClientService extends AbstractOuterClientService {

	private Map<HostPort, HostPortDcStatus> instanceStatus = new ConcurrentHashMap<>();

	private Map<String, Integer> cntMap = new ConcurrentHashMap<>();


	private OutClientInstanceStatus instanceStatus(HostPort hostPort) throws OuterClientException {
		HostPortDcStatus result = instanceStatus.get(hostPort);
		if (result == null) {
			return new OutClientInstanceStatus();
		}
		OutClientInstanceStatus outClientInstanceStatus = new OutClientInstanceStatus();
		outClientInstanceStatus.setEnv(result.getDc());
		outClientInstanceStatus.setIPAddress(result.getHost());
		outClientInstanceStatus.setPort(result.getPort());
		outClientInstanceStatus.setCanRead(result.isCanRead());
		outClientInstanceStatus.setSuspect(result.isSuspect());
		return outClientInstanceStatus;
	}

	@Override
	public Map<HostPort, OutClientInstanceStatus> batchQueryInstanceStatus(String cluster, Set<HostPort> instances) throws OuterClientException {
		Map<HostPort, OutClientInstanceStatus> result = new HashMap<>();
		for (HostPort instance: instances) {
			result.put(instance, instanceStatus(instance));
		}
		return result;
	}

	@Override
	public boolean clusterMigratePreCheck(String clusterName) throws OuterClientException {
		logger.info("[clusterMigratePreCheck]{}", clusterName);
		return true;
	}

	@Override
	public MigrationPublishResult doMigrationPublish(String clusterName, String primaryDcName, List<InetSocketAddress> newMasters) throws OuterClientException{
		logger.info("[doMigrationPublish]Cluster:{}, NewPrimaryDc:{}, Masters:{}", clusterName, primaryDcName,
				newMasters);
		String startTime = DateTimeUtils.currentTimeAsString();
		MigrationPublishResult res = new MigrationPublishResult("default-addr", clusterName, primaryDcName, newMasters);
		String endTime = DateTimeUtils.currentTimeAsString();
		res.setSuccess(true);res.setMessage("default-success");
		res.setStartTime(startTime);
		res.setEndTime(endTime);
		return res;
	}

	@Override
	public MigrationPublishResult doMigrationPublish(String clusterName, String shardName, String primaryDcName,
			InetSocketAddress newMaster) throws OuterClientException{

		logger.info("[doMigrationPublish]Cluster:{}, Shard:{}, NewPrimaryDc:{}, NewMaster:{}", clusterName, shardName,
				primaryDcName, newMaster);
		String startTime = DateTimeUtils.currentTimeAsString();
		MigrationPublishResult res = new MigrationPublishResult("default-addr", clusterName, primaryDcName, Arrays.asList(newMaster));
		String endTime = DateTimeUtils.currentTimeAsString();
		res.setSuccess(true);res.setMessage("default-success");
		res.setStartTime(startTime);
		res.setEndTime(endTime);
		return res;
	}

	@Override
	public ClusterInfo getClusterInfo(String clusterName) {
		ClusterInfo clusterInfo = new ClusterInfo();
		clusterInfo.setName(clusterName);
		clusterInfo.setGroups(Lists.newArrayList(new GroupInfo()));
		return clusterInfo;
	}

	@Override
	public List<ClusterInfo> getActiveDcClusters(String dc) throws Exception {
		return Collections.emptyList();
	}

	@Override
	public DcMeta getOutClientDcMeta(String dc) throws Exception {
		return new DcMeta();
	}

	@Override
	public boolean excludeIdcs(String clusterName, String[] idcs) throws Exception {
		return true;
	}

	@Override
	public boolean batchExcludeIdcs(List<ClusterExcludedIdcInfo> excludedClusterIdcs) throws Exception {
		return true;
	}

	@Override
	public void batchMarkInstance(MarkInstanceRequest markInstanceRequest) throws OuterClientException {
		logger.info("[batchMarkInstance]{}", markInstanceRequest);
		for (HostPortDcStatus hostPortDcStatus : markInstanceRequest.getHostPortDcStatuses()) {
			instanceStatus.put(new HostPort(hostPortDcStatus.getHost(), hostPortDcStatus.getPort()), hostPortDcStatus);
		}
		this.cntMap = markInstanceRequest.getInstanceCnt();
	}

	@Override
	public OuterClientDataResp<List<ClusterExcludedIdcInfo>> getAllExcludedIdcs() throws Exception {
		OuterClientDataResp<List<ClusterExcludedIdcInfo>> resp = new OuterClientDataResp<>();
		resp.setSuccess(true);
		resp.setResult(Collections.emptyList());
		return resp;
	}

	public Map<String, Integer> getCntMap() {
		return cntMap;
	}
}
